﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;

namespace Study.Ajax
{
    /// <summary>
    /// UploadFileHandler 的摘要说明
    /// </summary>
    public class UploadFileHandler : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            string path = context.Server.MapPath("../Files");//上传文件存储路径

            //如果提交的文件名是空，则不处理
            if (context.Request.Files.Count == 0 || string.IsNullOrWhiteSpace(context.Request.Files[0].FileName))
                return;
            //获取文件流
            Stream stream = context.Request.Files[0].InputStream;
            //获取文件名称
            string fileName = Path.GetFileName(context.Request.Files[0].FileName);
            //声明字节数组
            byte[] buffer;
            //为什么是4096呢？这是操作系统中最小的分配空间，如果你的文件只有100个字节，其实它占用的空间是4096个字节
            int bufferSize = 4096;
            //获取上传文件流的总长度
            long totalLength = stream.Length;
            //已经写入的字节数，用于做上传的百分比
            long writtenSize = 0;
            //创建文件
            using (FileStream fs = new FileStream(Path.Combine(path,fileName), FileMode.Create, FileAccess.Write))
            {
                //如果写入文件的字节数小于上传的总字节数，就一直写，直到写完为止
                while (writtenSize < totalLength)
                {
                    //如果剩余的字节数大于等于最小分配空间
                    if (totalLength - writtenSize >= bufferSize)
                    {
                        //用最小分配空间创建新的字节数组
                        buffer = new byte[bufferSize];
                    }
                    else
                    {
                        //用剩余的字节数创建字节数组
                        buffer = new byte[totalLength - writtenSize];
                    }
                    //读取上传的文件到字节数组
                    stream.Read(buffer, 0, buffer.Length);

                    //将读取的字节数组写入到新建的文件流中
                    fs.Write(buffer, 0, buffer.Length);

                    //增加写入的字节数
                    writtenSize += buffer.Length;

                    //计算当前上传文件的百分比
                    long percent = writtenSize * 100 / totalLength;
                    SendPercentToClient(percent);
                }
            }
        }

        private static void SendPercentToClient(long percent)
        {
            //当上传完毕后，保证处理程序能向客户端传回
            while (RequestProgressAsyncHandler.AsyncResults.Count == 0 && percent == 100)
            {
            }
            //因为本处理程序和"处理请求进度的程序"是并发的，
            //不能保证RequestProgressAsyncHandler.AsyncResults一定含有子项(有子项代表前台有获取上传进度的请求)
            if (RequestProgressAsyncHandler.AsyncResults.Count != 0)
            {
                RequestProgressAsyncHandler.AsyncResults[0].PercentNumber = percent;
                RequestProgressAsyncHandler.AsyncResults[0].DoCompleteTask();
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}